<template>
  <div class="leftWrap" :class="{ 'collapsed': isCollapsed }">
    <div class="toggle-btn" @click="toggleCollapse">{{ isCollapsed ? '>' : '<' }}</div>
        <Chart1 v-show="!isCollapsed" />
        <div class="now-area" v-show="!isCollapsed">点击了第{{nowArea}}区</div>
    </div>
    <div ref="canvasContainer" class="canvas-container"></div>
    <div class="tooltip" ref="tooltip"></div>
</template>

<script>
  import Chart1 from '@/components/Chart1.vue';
  import imgUrl1 from '@/assets/img/5.jpg';
  import imgUrl2 from '@/assets/img/6.jpg';
  import imgUrl3 from '@/assets/img/8.jpg';
  import imgRoad from '@/assets/img/road1.jpeg';

  import * as THREE from "three";
  import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
  // 添加CSS2D渲染器
  import { CSS2DRenderer, CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer.js';
  import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';

  const box1Path = '@/assets/gltf/box1/scene.gltf';
  export default {
    name: "普通仓库分6个区，每个区2行，高2，纵深10",
    components: {
      Chart1
    },
    computed: {},
    data() {
      return {
        isCollapsed: false,
        areaColors: {
          1: 0x5DACE3,
          2: 0x5de3af,
          3: 0xe35d86
        },
        nowArea: "",
        cubes: [
          [
            [3, 3, 4],
            [3, 3, 4],
          ], [
            [3, 3, 3],
            [3, 3, 3],
          ], [
            [8, 3, 2, 1, 1],
            [4, 1, 3, 1, 1],
          ]]
      };
    },
    mounted() {
      // 为cubes生成数据，第一层length为6，第二层length为2，第三层length为10，值为2
      this.cubes = Array.from({ length: 6 }, () => Array.from({ length: 2 }, () => Array.from({ length: 10 }, () => 2)));
      this.areaColors = this.generateRandomColors(this.cubes.length)

      // 初始化场景、相机、渲染器等
      this.initScene();
      // 创建立方体
      this.createCube();
      // 创建平面
      this.createPlane();
      this.animate();
      this.createControls()
      // 窗口大小自适应
      window.addEventListener('resize', this.onWindowResize)
    },
    methods: {
      // 随机生成颜色
      generateRandomColors(count) {
        const colors = {};
        for (let i = 1; i <= count; i++) {
          colors[i] = Math.floor(Math.random() * 0xFFFFFF);
          // colors[i] = 0xFFD18E
        }
        return colors;
      },
      toggleCollapse() {
        this.isCollapsed = !this.isCollapsed;
      },
      initScene() {
        // 1. 创建场景
        this.scene = new THREE.Scene()
        // 设置场景背景色为灰色
        this.scene.background = new THREE.Color(0x27304D);

        // 2. 创建相机（透视相机）
        this.camera = new THREE.PerspectiveCamera(
          75,  // 1. 视野角度(FOV - Field of View)- 单位是度(°)，表示相机垂直方向的视野范围。值越大，看到的场景越多(类似广角镜头)；值越小，看到的场景越少(类似长焦镜头)。通常设置在45-75度之间。
          window.innerWidth / window.innerHeight, // 2. 宽高比(aspect ratio)- 通常设置为渲染区域的宽度除以高度(如窗口宽高比)。这个值影响水平方向的视野。
          0.1, // 3. 近裁剪面(near clipping plane)- 相机能看到的最近距离。小于这个距离的物体不会被渲染。通常设置为一个较小的正数(如0.1)。
          1000 // 4. 远裁剪面(far clipping plane) - 相机能看到的最远距离。大于这个距离的物体不会被渲染。根据场景大小设置适当的值。
        );
        // 设置相机初始位置 - 俯视角度
        this.camera.position.set(-30, 5, 0); // x,y,z坐标
        // lookAt()方法可以让相机指向一个特定的点，它会受OrbitControls影响
        // this.camera.lookAt(5, 0, 0);

        // 3. 创建渲染器
        this.renderer = new THREE.WebGLRenderer({
          antialias: true,
          alpha: true
        });
        this.renderer.shadowMap.enabled = true;
        this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
        this.renderer.setSize(window.innerWidth, window.innerHeight)
        // 4. 挂载到DOM
        this.$refs.canvasContainer.appendChild(this.renderer.domElement)

        // 添加环境光和方向光
        const ambientLight = new THREE.AmbientLight(0xffffff, 1);
        this.scene.add(ambientLight);

        // 增强平行光强度和添加辅助光
        const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
        directionalLight.position.set(10, 20, 10);
        directionalLight.castShadow = true;
        this.scene.add(directionalLight);

        // 添加第二个辅助平行光
        const directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.5);
        directionalLight2.position.set(-10, 20, -10);
        this.scene.add(directionalLight2);

        // 添加半球光模拟环境反射
        const hemisphereLight = new THREE.HemisphereLight(0xffffff, 0x444444, 0.6);
        hemisphereLight.position.set(0, 20, 0);
        this.scene.add(hemisphereLight);


        // 创建CSS2D渲染器
        this.labelRenderer = new CSS2DRenderer();
        this.labelRenderer.setSize(window.innerWidth, window.innerHeight);
        this.labelRenderer.domElement.style.position = 'absolute';
        this.labelRenderer.domElement.style.top = '0';
        this.labelRenderer.domElement.style.pointerEvents = 'none';
        this.$refs.canvasContainer.appendChild(this.labelRenderer.domElement);

        // 创建区域辅助线坐标系，X(红色)、Y(绿色)、Z(蓝色)
        const axesHelper = new THREE.AxesHelper(50);
        axesHelper.position.set(0, 0, 0);
        this.scene.add(axesHelper);

        const grid = new THREE.GridHelper(200, 50, 0x888888, 0x444444);
        grid.userData.isLight = true
        grid.position.y = -2; // 稍微抬高避免与地面重叠
        this.scene.add(grid);
      },
      // 创建一个平面
      createPlane() {
        // 1.大平面
        const planeSize = 100;
        const geometry = new THREE.PlaneGeometry(planeSize, planeSize);
        const material = new THREE.MeshBasicMaterial({
          color: 0x1E2430,
          side: THREE.DoubleSide,
        });
        this.plane = new THREE.Mesh(geometry, material);
        this.plane.rotation.x = -Math.PI / 2;
        this.plane.position.y = -2;
        this.scene.add(this.plane);

        // this.createWallRoof(planeSize);

        // 区域间的间距
        const areaSpacing = 10;
        const group = new THREE.Group();
        for (let area = 0; area < this.cubes.length; area++) {
          const areaGeometry = new THREE.PlaneGeometry(30, 10);

          const areaMaterial = new THREE.MeshBasicMaterial({
            color: this.areaColors[area + 1],
            transparent: true,
            opacity: 0.3,
            side: THREE.DoubleSide,
          });

          const areaPlane = new THREE.Mesh(areaGeometry, areaMaterial);
          areaPlane.rotation.x = -Math.PI / 2;
          areaPlane.position.x = 8;
          areaPlane.position.y = -1.9;
          areaPlane.position.z = area * areaSpacing + 1;
          areaPlane.userData.isAreaPlane = true; // 标记为区域平面
          areaPlane.userData.areaNumber = area + 1; // 存储区域编号

          group.add(areaPlane);
        }
        // group置于大平面正中间
        group.position.x = -5;
        group.position.y = 0;
        group.position.z = -20;

        this.scene.add(group);
      },
      // 创建立方体
      async createCube() {
        const geometry = new THREE.BoxGeometry(2, 1, 1);
        const textureLoader = new THREE.TextureLoader();
        const texture = textureLoader.load(imgUrl2);
        texture.colorSpace = THREE.SRGBColorSpace;

        const loader = new GLTFLoader();
        this.cubeGroups = [];

        // 区域间的间距
        const areaSpacing = 10;

        // 遍历每个区域
        for (let area = 0; area < this.cubes.length; area++) {
          const areaCubes = this.cubes[area];
          const maxCols = Math.max(...areaCubes.map(row => row.length));

          // 区域起始位置(每个区域从0,0开始)
          const areaStartX = 0;
          const areaStartZ = area * areaSpacing; // 区域间保持间距

          // 创建区域辅助线坐标系，X(红色)、Y(绿色)、Z(蓝色)
          // const axesHelper = new THREE.AxesHelper(50);
          // axesHelper.position.set(0, 0, areaStartZ);
          // this.scene.add(axesHelper);

          // 创建区域标签
          const areaLabelDiv = document.createElement('div');
          areaLabelDiv.className = 'area-label';
          // 计算该区域货箱总数
          const totalBoxes = areaCubes.flat().reduce((sum, count) => sum + count, 0);
          // areaLabelDiv.textContent = `${area + 1}区 (共${totalBoxes}个货箱)`;
          areaLabelDiv.textContent = `${area + 1}区`;
          areaLabelDiv.style.color = 'white';
          areaLabelDiv.style.fontSize = '20px';
          areaLabelDiv.style.textShadow = '0 0 5px black';

          const areaLabel = new CSS2DObject(areaLabelDiv);
          areaLabel.position.set(maxCols - 5, -1.9, areaStartZ + areaCubes.length / 2 - 20);
          this.scene.add(areaLabel);

          // 遍历当前区域的每一行
          for (let row = 0; row < areaCubes.length; row++) {
            // 遍历当前区域的每一列
            for (let col = 0; col < areaCubes[row].length; col++) {
              const cubeCount = areaCubes[row][col];
              const cubeGroup = new THREE.Group();

              // 加载GLTF模型
              const gltf = await loader.loadAsync('src/assets/gltf/box1/scene.gltf');

              // 创建指定数量的立方体
              for (let i = 0; i < cubeCount; i++) {
                const material = new THREE.MeshBasicMaterial({
                  color: this.areaColors[area + 1], // 使用区域对应的颜色
                });
                const cube = new THREE.Mesh(geometry, material);
                cube.position.set(0, -1.5 + i, 0);

                // 添加边框
                const edges = new THREE.EdgesGeometry(geometry);
                const lineMaterial = new THREE.LineBasicMaterial({
                  color: 0xeeeeee,
                  linewidth: 1
                });
                const wireframe = new THREE.LineSegments(edges, lineMaterial);
                wireframe.position.copy(cube.position);
                cubeGroup.add(wireframe);
                cubeGroup.add(cube);

                // const model = gltf.scene.clone();

                // const boxSize = new THREE.Box3().setFromObject(model).getSize(new THREE.Vector3());
                // model.position.set(0, -1.5 + i * boxSize.y, 0);  // 根据实际高度堆叠
                // model.scale.set(1, 1, 1); // 将缩放比例从0.5调整为1

                // cubeGroup.add(model);
              }

              cubeGroup.position.set(
                areaStartX + col * 2 - 5, // 从0开始向右排列
                0,
                areaStartZ + row * 2 - 20 // 从0开始向下排列
              );
              this.scene.add(cubeGroup);
              this.cubeGroups.push({
                group: cubeGroup,
                count: cubeCount,
                area: area + 1 // 区域编号从1开始
              });
            }
          }
        }

        // 创建射线检测器和鼠标向量
        const raycaster = new THREE.Raycaster();
        const mouse = new THREE.Vector2();

        // 添加鼠标移动事件
        window.addEventListener('mousemove', (event) => {
          mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
          mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

          // 检测射线与立方体组的相交
          raycaster.setFromCamera(mouse, this.camera);
          // 获取所有立方体组的父级对象
          // intersects数组中包含所有相交的物体
          const intersects = raycaster.intersectObjects(
            this.cubeGroups.flatMap(g => g.group.children),
            true // 启用递归检测
          );

          if (this.$refs.tooltip) {
            if (intersects.length > 0) {
              const intersectedModel = intersects[0].object;
              const cubeGroup = this.cubeGroups.find(g =>
                g.group.children.some(child => {
                  // 递归查找父级关系
                  let obj = intersectedModel;
                  while (obj.parent) {
                    if (obj.parent === g.group) return true;
                    obj = obj.parent;
                  }
                  return false;
                })
              );

              if (cubeGroup) {
                this.$refs.tooltip.style.display = 'block';
                this.$refs.tooltip.style.left = `${event.clientX + 10}px`;
                this.$refs.tooltip.style.top = `${event.clientY + 10}px`;
                this.$refs.tooltip.textContent = `这一摞有 ${cubeGroup.count} 个货箱`;
                return;
              }
            }
            this.$refs.tooltip.style.display = 'none';
          }
        });


        // 添加点击事件监听
        this.renderer.domElement.addEventListener('click', (event) => {
          mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
          mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

          raycaster.setFromCamera(mouse, this.camera);
          const intersects = raycaster.intersectObjects(
            this.cubeGroups.flatMap(g => g.group.children),
            true
          );

          if (intersects.length > 0) {
            const intersectedModel = intersects[0].object;
            const cubeGroup = this.cubeGroups.find(g =>
              g.group.children.some(child => {
                let obj = intersectedModel;
                while (obj.parent) {
                  if (obj.parent === g.group) return true;
                  obj = obj.parent;
                }
                return false;
              })
            );

            if (cubeGroup) {
              this.nowArea = cubeGroup.area;
            }
          }
        }, false);

        // 添加区域平面点击检测
        const areaPlanes = this.scene.children.filter(
          obj => obj instanceof THREE.Mesh && obj.userData.isAreaPlane
        );

        window.addEventListener('click', (event) => {
          mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
          mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

          raycaster.setFromCamera(mouse, this.camera);
          const intersects = raycaster.intersectObjects(areaPlanes);

          if (intersects.length > 0) {
            const areaPlane = intersects[0].object;
            this.nowArea = areaPlane.userData.areaNumber;
          }
        });
      },
      // 动画循环
      animate() {
        requestAnimationFrame(this.animate)
        this.renderer.render(this.scene, this.camera)
        this.labelRenderer.render(this.scene, this.camera)
      },
      onWindowResize() {
        this.camera.aspect = window.innerWidth / window.innerHeight
        // 更新投影矩阵
        this.camera.updateProjectionMatrix()
        this.renderer.setSize(window.innerWidth, window.innerHeight)
      },
      // 相机控件
      createControls() {
        this.controls = new OrbitControls(this.camera, this.renderer.domElement)
        // 增加平移速度
        this.controls.panSpeed = 2.0;
        // 增加缩放速度
        this.controls.zoomSpeed = 1.2;
        // 增加旋转速度
        this.controls.rotateSpeed = 1.0;

        // 禁用阻尼效果
        this.controls.enableDamping = false;
        // 禁用惯性效果
        this.controls.enableInertia = false;

        // 设置平移限制
        this.controls.maxPolarAngle = Math.PI; // 允许完全垂直旋转
        this.controls.minAzimuthAngle = -Infinity;
        this.controls.maxAzimuthAngle = Infinity;

        this.controls.addEventListener('change', () => {
          this.renderer.render(this.scene, this.camera)
        })
      }
    },
    unmounted() {
      window.removeEventListener('resize', this.onWindowResize)
      // if (this.renderer) {
      //   this.renderer.dispose()
      //   this.$refs.canvasContainer.removeChild(this.renderer.domElement)
      // }
    }
  };
</script>

<style lang="scss">
  * {
    margin: 0;
    padding: 0;
  }

  .leftWrap {
    width: 300px;
    height: calc(100vh - 20px);
    background: rgba(33, 50, 81, 0.7);
    position: absolute;
    left: 10px;
    top: 10px;
    z-index: 1000;
    border-radius: 10px;
    transition: all 0.3s ease;
    padding: 10px;
    box-sizing: border-box;

    &.collapsed {
      width: 40px;
      padding: 10px 5px;
    }

    .toggle-btn {
      position: absolute;
      right: 0;
      top: 50%;
      transform: translateY(-50%);
      width: 30px;
      height: 60px;
      background: rgba(33, 50, 81, 0.7);
      border-radius: 5px;
      display: flex;
      align-items: center;
      justify-content: center;
      color: white;
      font-weight: bold;
      cursor: pointer;
      user-select: none;
      transition: all 0.3s ease;

      &:hover {
        background: rgba(33, 50, 81, 0.9);
      }
    }
  }

  .canvas-container {
    width: 100vw;
    height: 100vh;
    overflow: hidden;
  }

  .area-label {
    transform: translate(-50%, -50%);
    white-space: nowrap;
  }

  .tooltip {
    position: absolute;
    background: rgba(0, 0, 0, 0.7);
    color: white;
    padding: 8px 12px;
    border-radius: 4px;
    pointer-events: none;
    display: none;
    z-index: 100;
  }

  .now-area {
    color: #fff;
    margin-top: 40px;
    font-size: 20px;
  }
</style>